-
-
Notifications
You must be signed in to change notification settings - Fork 31.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Logi Circle component, camera and sensor platform #16540
Conversation
…s not supported by device. Added services for recording livestream and taking a snapshot from the livestream.
…assistant components and into the logi circle API wrapper. Added services.yaml entries for logi services.
…e` and tidy up in preparation for pull request. - Renamed `logi_set_mode` to `logi_set_config`. - Live stream recording and snapshot methods now respect whitelisted path configuration. - Added `streaming_mode` and `speaker_volume` sensors. - Moved model-specific turn on/off logic to `logi_circle` library.
asyncio.shield(self._camera.record_livestream( | ||
stream_file, timedelta(seconds=duration)), loop=self.hass.loop) | ||
|
||
async def livestream_snapshot(self, filename): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A quick explanation on why this was implemented when there's already a generic snapshot
service for cameras:
When not live streaming, Logi cameras (particularly battery-powered devices) go into a low power state, only taking a snapshot every 1-5 minutes. This cached image is what the async_camera_image
method uses.
This method exists if you really need to wake the camera from sleep immediately to take a snapshot. I didn't want this to be the default source for camera stills as it increases battery drain.
Can you rename the component to logi_circle |
@balloob Done. |
|
||
from homeassistant.helpers import config_validation as cv | ||
from homeassistant.components.logi_circle import ( | ||
DOMAIN, CONF_ATTRIBUTION) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This platform belongs to the camera domain. Import the logi_circle domain as another name.
from homeassistant.components.logi_circle import (
DOMAIN as LOGI_CIRCLE_DOMAIN, ...
DOMAIN, CONF_ATTRIBUTION) | ||
from homeassistant.components.camera import ( | ||
Camera, PLATFORM_SCHEMA, CAMERA_SERVICE_SCHEMA, SUPPORT_ON_OFF, | ||
ATTR_ENTITY_ID, ATTR_FILENAME, DOMAIN as CAMERA_DOMAIN) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This domain should be imported as domain. 😉
}) | ||
|
||
|
||
async def async_setup_platform(hass, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please break the line after the first parenthesis and then fill out as far as possible.
|
||
def __init__(self, hass, camera, device_info): | ||
"""Initialize Logi Circle camera.""" | ||
super(LogiCam, self).__init__() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super().__init__()
'firmware': self._camera.firmware, | ||
'generation': self._camera.model_generation, | ||
'ip_address': self._camera.ip_address, | ||
'mac_address': self._camera.mac_address, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The mac address could be used instead in the unique id property.
https://developers.home-assistant.io/docs/en/entity_registry_index.html
https://developers.home-assistant.io/docs/en/entity_index.html#generic-properties
self._icon = 'mdi:{}'.format(SENSOR_TYPES.get(self._sensor_type)[2]) | ||
self._name = "{0} {1}".format( | ||
self._camera.name, SENSOR_TYPES.get(self._sensor_type)[0]) | ||
self._state = STATE_UNKNOWN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use None
to represent unknown state.
ATTR_ATTRIBUTION: CONF_ATTRIBUTION, | ||
'battery_saving_mode': ('on' if self._camera.battery_saving | ||
else 'off'), | ||
'firmware': self._camera.firmware, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above about appropriate state attributes.
'firmware': self._camera.firmware, | ||
'generation': self._camera.model_generation, | ||
'ip_address': self._camera.ip_address, | ||
'mac_address': self._camera.mac_address, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Define unique id property with this.
def icon(self): | ||
"""Icon to use in the frontend, if any.""" | ||
if (self._sensor_type == 'battery_level' and | ||
self._state != STATE_UNKNOWN): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use STATE_UNKNOWN
.
else: | ||
state = getattr(self._camera, self._sensor_type, STATE_UNKNOWN) | ||
if isinstance(state, bool): | ||
self._state = 'on' if state is True else 'off' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use STATE_ON
and STATE_OFF
from const.py. But probably we should instead make a binary sensor platform for that type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The two binary sensors the camera exposes through the sensor platform are:
- streaming mode: determines whether the camera can return video/stills and whether it will record activities (motion, etc)
- privacy mode: determines whether the camera will record activities if they're detected
Neither of these seem to fit neatly into any existing binary sensor class, which is why I opted to make them sensors instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can define binary sensors without a specific device class. If a sensor only has a binary state, it belongs with the binary sensor platform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, my bad. As you advised, I'll migrate these sensors to a binary sensor in my next PR.
* Added timeout of 15s to logi_circle initial setup requests (login and grabbing cameras). * Added unique ID (uses MAC address for camera platform, MAC address + sensor type for sensor platform). * Added battery level and battery charging attributes to camera. * Removed static attributes from device_state_attributes. * Replaced STATE_UNKNOWN with None, replaced ‘on’ & ‘off’ with STATE_ON and STATE_OFF. * Removed redundant SCAN_INTERVAL in sensor, removed redundant hass param from async_setup_platform in camera and sensor. * Style tweaks.
…h other components.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
I would suggest moving the sensors that have binary states to the binary_sensor platform. That can happen in another PR though.
@MartinHjelmare Thanks for the review! |
Description:
This adds the
logi_circle
component, camera and sensor platforms for Logi Circle 1st and 2nd gen cameras.Screenshot of working configuration (2x Logi Cameras shown)
Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.io#6249
Example entry for
configuration.yaml
(if applicable):Checklist:
tox
. Your PR cannot be merged unless tests passIf user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
REQUIREMENTS
variable (example).requirements_all.txt
by runningscript/gen_requirements_all.py
..coveragerc
.If the code does not interact with devices: